package com.itlxd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itlxd.common.ThreadLocalUtils;
import com.itlxd.dto.PageDTO;
import com.itlxd.dto.SetmealDTO;
import com.itlxd.entity.Category;
import com.itlxd.entity.Setmeal;
import com.itlxd.entity.SetmealDish;
import com.itlxd.enums.EYesOrNo;
import com.itlxd.exception.SetmealException;
import com.itlxd.global.SysConstants;
import com.itlxd.global.SysMessages;
import com.itlxd.mapper.SetmealMapper;
import com.itlxd.service.ICategoryService;
import com.itlxd.service.ISetmealDishService;
import com.itlxd.service.ISetmealService;
import com.itlxd.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 套餐 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2021-12-25
 */
@Transactional(propagation = Propagation.SUPPORTS)
@Service
public class SetmealServiceImpl implements ISetmealService {

    @Autowired
    private SetmealMapper setMealMapper;
    @Autowired
    private ISetmealDishService setmealDishService;
    @Autowired
    private ICategoryService categoryService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Integer count(Long categoryId) {
        LambdaQueryWrapper<Setmeal> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.eq(null != categoryId, Setmeal::getCategoryId, categoryId);
        return setMealMapper.selectCount(lambdaQuery);
    }

    @Override
    public IPage<SetmealVO> listPageSetmeals(PageDTO pageDTO) {
        IPage<Setmeal> page = new Page(pageDTO.getPage(), pageDTO.getPageSize());
        LambdaQueryWrapper<Setmeal> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.like(null != pageDTO.getName(), Setmeal::getName, pageDTO.getName());
        IPage<Setmeal> setmealIPage = setMealMapper.selectPage(page, lambdaQuery);

        IPage<SetmealVO> result = new Page<>();
        result.setTotal(setmealIPage.getTotal());
        List<SetmealVO> setmealVOList = setmealIPage.getRecords().stream().map(setmeal -> {
            SetmealVO setmealVO = new SetmealVO();
            BeanUtils.copyProperties(setmeal, setmealVO);
            Category category = categoryService.getById(setmeal.getCategoryId());
            setmealVO.setCategoryName(category.getName());
            return setmealVO;
        }).collect(Collectors.toList());
        result.setRecords(setmealVOList);

        return result;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer insertSetmeal(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        int row1 = setMealMapper.insert(setmeal);

        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        List<SetmealDish> setmealDishList = setmealDishes.stream().map(item -> {
            item.setSetmealId(setmeal.getId().toString());
            return item;
        }).collect(Collectors.toList());
        int row2 = setmealDishService.insertBatch(setmealDishList);
        //删除redis中缓存的数据
        redisTemplate.delete(SysConstants.SETMEAL_CACHE + "::" + setmealDTO.getCategoryId() + "_1");

        return row1 + row2 == 1 + setmealDishList.size() ? SysConstants.YES: SysConstants.NO;
    }

    @Override
    public SetmealVO getById(Long id) {
        SetmealVO setmealVO = new SetmealVO();
        Setmeal setmeal = setMealMapper.selectById(id);
        List<SetmealDish> setmealDishList = setmealDishService.listSetmealDishes(id.toString());

        BeanUtils.copyProperties(setmeal, setmealVO);
        setmealVO.setSetmealDishes(setmealDishList);
        return setmealVO;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer updateSetmeal(SetmealDTO setmealDTO) {
        long oldCatId = setMealMapper.selectById(setmealDTO.getId()).getCategoryId();

        int row1 = setMealMapper.updateById(setmealDTO);
        //删除后新增菜品数据
        setmealDishService.deleteBatchBySetmealId(Arrays.asList(setmealDTO.getId()));
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        int row2 = 0;
        if (null != setmealDishes && setmealDishes.size() > 0) {
            List<SetmealDish> setmealDishList = setmealDishes.stream().map(item -> {
                item.setSetmealId(setmealDTO.getId().toString());
                return item;
            }).collect(Collectors.toList());
            row2 += setmealDishService.insertBatch(setmealDishes);
        }
        //删除redis中缓存的数据
        if (oldCatId == setmealDTO.getCategoryId()) {
            redisTemplate.delete(SysConstants.SETMEAL_CACHE + "::" + oldCatId + "_1");
        }else {
            redisTemplate.delete(SysConstants.SETMEAL_CACHE + "::" + oldCatId + "_1");
            redisTemplate.delete(SysConstants.SETMEAL_CACHE + "::" + setmealDTO.getCategoryId() + "_1");
        }

        return row1 + row2 == 1 + setmealDishes.size() ? SysConstants.YES : SysConstants.NO;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer deleteBatchSetmeals(Long[] ids) {
        Long catId = setMealMapper.selectById(ids[0]).getCategoryId();
        //判断是否有启售中的数据
        LambdaQueryWrapper<Setmeal> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.in(Setmeal::getId, ids)
                .eq(Setmeal::getStatus, SysConstants.YES);
        Integer onSaleNum = setMealMapper.selectCount(lambdaQuery);
        if (onSaleNum > SysConstants.NUM_ZERO) {
            throw new SetmealException(SysMessages.SETMEAL_ON_SALE);
        }

        int row1 = setMealMapper.deleteBatchIds(Arrays.asList(ids));
        int row2 = setmealDishService.deleteBatchBySetmealId(Arrays.asList(ids));

        //因为批量删除和单个删除用的同一个接口，批量删除的数据可能包含多个分类，所以这里只做单个删除时的处理
        if (ids.length == 1) {
            redisTemplate.delete(SysConstants.SETMEAL_CACHE + "::" + catId + "_1");
        } else {
            //全部删除
            Set keys = redisTemplate.keys(SysConstants.SETMEAL_CACHE + "::*");
            redisTemplate.delete(keys);
        }

        return row1 + row2 > SysConstants.NUM_ONE ? SysConstants.YES : SysConstants.NO;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer updateBatchStatusSetmeals(Long[] ids, Integer status) {
        Long catId = setMealMapper.selectById(ids[0]).getCategoryId();
        int count = 0;
        for (Long id : ids) {
            Setmeal setmeal = new Setmeal();
            setmeal.setId(id).setStatus(status);
            setMealMapper.updateById(setmeal);
            count++;
        }
        //因为批量删除和单个删除用的同一个接口，批量删除的数据可能包含多个分类，所以这里只做单个删除时的处理
        if (ids.length == 1) {
            redisTemplate.delete(SysConstants.SETMEAL_CACHE + "::" + catId + "_1");
        } else {
            //全部删除
            Set keys = redisTemplate.keys(SysConstants.SETMEAL_CACHE + "::*");
            redisTemplate.delete(keys);
        }
        return count;
    }

    @Cacheable(value = "setmealCache", key = "#setmeal.categoryId + '_' +#setmeal.status")
    @Override
    public List<Setmeal> listSetmeals(Setmeal setmeal) {
        LambdaQueryWrapper<Setmeal> lambdaQuery = new LambdaQueryWrapper<>();
        lambdaQuery.eq(null != setmeal.getCategoryId(), Setmeal::getCategoryId, setmeal.getCategoryId())
                .eq(null != setmeal.getStatus(), Setmeal::getStatus, setmeal.getStatus());
        return setMealMapper.selectList(lambdaQuery);
    }
}